//
// Ishtar C++ Utility Library
//
// Task Facility - Work State Header
//

#ifndef __ISHTAR_TASK_WORK_STATE_H
#define __ISHTAR_TASK_WORK_STATE_H

#include <Ishtar/Ishtar.h>

#if defined( ISHTAR_COMPILER_HAS_PRAGMA_ONCE )
#pragma once
#endif

#include <Ishtar/Interlocked/InterlockedStateMachine.h>


namespace Ishtar
{

namespace Task
{

///////////////////////////////////////////////////////////////////////////////
//
// Work State Values
//

enum WorkState
{
    WORK_STATE_UNSTARTED    = 0,
    WORK_STATE_DELAYING     = 1,
    WORK_STATE_DELAYED      = 2,     // waiting delay timer
    WORK_STATE_ORDERING     = 3,
    WORK_STATE_ORDERED      = 4,     // waiting all orders are cleared
    WORK_STATE_TO_RPOVE     = 5,
    WORK_STATE_PROVING      = 6,
    WORK_STATE_QUEUING      = 7,     // add to executor
    WORK_STATE_TO_CANCEL    = 8,
    WORK_STATE_READY        = 9,

    // below states are beyond ready.

    WORK_STATE_RUNNING      = 10,
    WORK_STATE_CANCELING    = 11,
    WORK_STATE_RUNNED       = 0x10C,  // 0x100 + 12
    WORK_STATE_CANCELED     = 0x10D,  // 0x100 + 13
};


///////////////////////////////////////////////////////////////////////////////
//
// Work Event Tags
//

struct WorkEventDelay  {};
struct WorkEventOrder  {};
struct WorkEventQueue  {};
struct WorkEventWait   {};
struct WorkEventRun    {};
struct WorkEventCancel {};
struct WorkEventEnd    {};


///////////////////////////////////////////////////////////////////////////////
//
// Work State Machine
//

class WorkStateMachine
    : public InterlockedStateMachine< WorkStateMachine, WorkState, WORK_STATE_UNSTARTED >
{
public:
    
    template< typename EventType > struct TransitRule;

    template<>
    struct TransitRule< WorkEventDelay > :
        Transition1< WORK_STATE_UNSTARTED, WORK_STATE_DELAYING >
    {};

    template<>
    struct TransitRule< WorkEventOrder > :
        Transition2< WORK_STATE_UNSTARTED, WORK_STATE_ORDERING,
                     WORK_STATE_DELAYED,   WORK_STATE_ORDERING >
    {};

    template<>
    struct TransitRule< WorkEventQueue > :
        Transition2< WORK_STATE_ORDERING,  WORK_STATE_QUEUING,
                     WORK_STATE_PROVING,   WORK_STATE_QUEUING >
    {};

    template<>
    struct TransitRule< WorkEventWait > :
        Transition2< WORK_STATE_PROVING, WORK_STATE_ORDERED,
                     WORK_STATE_QUEUING, WORK_STATE_READY >
    {};

    template<>
    struct TransitRule< WorkEventRun > :
        Transition2< WORK_STATE_READY,   WORK_STATE_RUNNING,
                     WORK_STATE_QUEUING, WORK_STATE_RUNNING >
    {};

    template<>
    struct TransitRule< WorkEventCancel > :
        Transition2< WORK_STATE_ORDERED, WORK_STATE_CANCELING,
                     WORK_STATE_READY,   WORK_STATE_CANCELING >
    {};

    template<>
    struct TransitRule< WorkEventEnd > :
        Transition2< WORK_STATE_RUNNING,   WORK_STATE_RUNNED,
                     WORK_STATE_CANCELING, WORK_STATE_CANCELED >
    {};
};


///////////////////////////////////////////////////////////////////////////////

} // namespace Task

} // namespace Ishtar

#endif // __ISHTAR_TASK_WORK_STATE_H
